package com.kun.demo05_threadCommunication;

import org.junit.Test;

//生产者消费者问题---解决方法2：使用信号灯法
public class Solution02 {

    @Test
    public void test() throws InterruptedException {
        TvProgram program = new TvProgram();
        Player player = new Player();
        player.program = program;
        Watcher watcher = new Watcher();
        watcher.program = program;
        player.start();
        watcher.start();

        Thread.sleep(5_000);
    }

    //1. 生产者--演员
    class Player extends Thread {

        TvProgram program;


        public void run() {

            for (int i = 0; i < 20; i++) {
                if (i % 2 == 0){
                    try {
                        program.produce(new TvProgram("《星球大战》第" + (i + 1) + "集"));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                    try {
                        program.produce(new TvProgram("《复仇者联盟》第" + (i + 1) + "集"));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

        }

    }


    //2. 消费者--观众
    class Watcher extends Thread {

        TvProgram program;

        public void run() {
            for (int i = 0; i < 20; i++) {
                if (i % 2 == 0){
                    try {
                        program.watch(new TvProgram("《星球大战》第" + (i + 1) + "集"));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }else{
                    try {
                        program.watch(new TvProgram("《复仇者联盟》第" + (i + 1) + "集"));
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }

        }
    }


    //3. 产品--节目
    class TvProgram {
        //信号灯，False表示空闲（演员等待，观众观看），True表示忙碌（演员表演，观众等待）
        boolean flag = true;
        String programName;

        public TvProgram() {
        }

        public TvProgram(String programName) {
            this.programName = programName;
        }

        //3.1 生产者生产节目
        public synchronized void produce(TvProgram tvProgram) throws InterruptedException {
            //3.1.1 观众正在观看，演员等待
            if (!flag){
                this.wait();
            }
            //3.1.2 开始演出
            System.out.println("开始播放节目：" + tvProgram.programName);

            //3.1.3 通知观众观看
            flag = !flag;
            this.notifyAll();
        }

        //3.2 消费者观看节目
        public synchronized void watch(TvProgram tvProgram) throws InterruptedException {
            //3.2.1 观众等待，演员表演
            if (flag) {
                this.wait();
            }
            //3.2.2 开始观看
            System.out.println("观看节目：" + tvProgram.programName);

            //3.2.3 通知演员等待
            flag = !flag;
            this.notifyAll();
        }
    }





}
